
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>

#include "../luaParameters.h"
#include "../global.h"
#include <iostream>
#include <boost/filesystem.hpp>
#include <log/log.h>
#include <appendix/phy_constants.h>
#include <boost/signals2/signal.hpp>
#include <boost/bind.hpp>
#include <boost/regex.hpp>
#include <thread>
#include <boost/thread/mutex.hpp>
#include <iostream>


namespace LuaHelp{
	sol::table open_luaParameters(sol::this_state L) ;
}

namespace lua{
	static luaParameters globalP;
	luaExpression::luaExpression():
	m_bNeedEvaluate(false),
	m_bValid(true),
	m_bSynatexError(false)
	{
	}


	double luaExpression::to_double()
	{
		return 0.0;
	}
	void luaExpression::build() const
	{
	}

	void luaExpression::set_parameters(std::shared_ptr<lua::luaParameters> p){
		if(m_parameters != p){
			m_parameters = p;
			m_bNeedEvaluate = true;
			build();
		}
	}

	luaDoubleExpression::luaDoubleExpression()
	:m_value(0.0)
	,m_expr("0")
	 {
	 }

	luaDoubleExpression::luaDoubleExpression(const std::string& expr){
		set_expression_impl(expr);
	}
	luaDoubleExpression::luaDoubleExpression(double d)
	:m_value(d)
	{
		set_expression(d);
	}

	void luaDoubleExpression::set_parameters(std::shared_ptr<lua::luaParameters> p){
		luaExpression::set_parameters(p);
	}
	void luaDoubleExpression::set_expression(const std::string& expr)
	{
		set_expression_impl(expr);
	}
	void luaDoubleExpression::set_expression(double expr)
	{
		auto str = (boost::format("%.16g") % expr).str();
		set_expression_impl(str);
	}

	void luaDoubleExpression::set_expression_impl(const std::string& expr)
	{
		m_expr = expr;
		m_bNeedEvaluate = true;
		m_bValid = false;
		m_bSynatexError = !(globalP.check_expression(expr));
		if( !m_bSynatexError ){
			bool res = globalP.evaluate(expr, m_value);
			if(res){
				m_bNeedEvaluate = false;
				m_bValid = true;
			}
		}else{
			//logs::error_log( "exprssion synatex error: %s",expr.c_str() );
		}
	}

	void luaDoubleExpression::build() const
	{
		if(!m_bNeedEvaluate) return;

		if( m_parameters )
		{
			m_bValid = m_parameters->evaluate(m_expr, m_value);
		}else{
			m_bValid = false;
		}
		//logs::error_log("parameters evaluate: %s",m_epsr.c_str() );
		//logs::error_log( "exprssion synatex error: %s",m_epsr.c_str() );
	}
	double luaDoubleExpression::operator()(void) const
	{
		if(!m_bNeedEvaluate) return m_value;
		build();
		return m_value;
	}
	double luaDoubleExpression::operator()(bool& ok) const
	{
		ok = false;
		if(m_bSynatexError){
			return m_value;
		}
		if(!m_bNeedEvaluate){
			ok = true;
			return m_value;
		}
		build();
		if( m_bValid ) ok = true;
		return m_value;
	}

	bool luaDoubleExpression::valuate(double& v) const
	{
		bool ok;
		v = (*this)(ok);
		return ok;
	}



	bool luaDoubleExpression::operator==(const luaDoubleExpression& rhs) const
	{
		if( m_expr != rhs.m_expr ) return false;
		if( m_parameters != rhs.m_parameters ) return false;
		return true;
	}
	bool luaDoubleExpression::operator!=(const luaDoubleExpression& rhs) const
	{
		return !operator==(rhs);
	}

};


